#include "VProjectTreeWidget.h"
#include "VFunctions.h"
#include "VGlobal.h"
#include "VInputDialog.h"
#include "VProjectAttributeDialog.h"
#include "VRemoveFileDialog.h"
#include "VProjectData.h"

#include <QMessageBox>
#include <QDrag>
#include <QDebug>
#include <QDragEnterEvent>
#include <QPainter>
#include <QMouseEvent>
#include <QMimeData>
#include <QJsonArray>
#include <QJsonDocument>
#include <QFileInfo>
#include <QToolTip>
#include <QFileDialog>
#include <functional>

VProjectTreeWidget::VProjectTreeWidget(QWidget *parent) : QTreeWidget(parent),
    _content_menu(this),
    _append_menu(this)
{
    this->setObjectName("project_treewidget");


}

void VProjectTreeWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    {
        event->accept();
        qDebug() << "dragEnterEvent accept";
    }
    else
    {
        event->ignore();
        qDebug() << "dragEnterEvent ignore";
    }


//    _darg_item = nullptr;
//    _darg_item = this->itemAt(event->pos());
//    if(_darg_item == nullptr)
//    {
//        event->setAccepted(false);
//        return;
//    }
//    _darg_item_type = get_item_data(_darg_item).type;
//    if(_darg_item_type == TreeWidgetItemType::PROJECT)
//    {
//        event->setAccepted(false);
//        return;
//    }
//    qDebug() << "dragEnterEvent";
//    event->setAccepted(true);

}

void VProjectTreeWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
    //qDebug()<<"dragLeaveEvent";
}

#define BORDERHEIGHT 3
void VProjectTreeWidget::dragMoveEvent(QDragMoveEvent *event)
{
    //QToolTip::hideText();

    if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    {
        QByteArray itemData = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
        QTreeWidgetItem *dragItem = (QTreeWidgetItem*)((void*)QVariant(itemData).toULongLong());
        auto item = itemAt(event->pos());
        auto data = get_item_data(item);
        if(item != nullptr && is_parent(dragItem, item) == false
                && get_top_item(dragItem) == get_top_item(item) &&
                get_item_data(item).type != TreeWidgetItemType::FILE &&
                is_custom_folder_child(item))
        {
            m_rect = visualItemRect(item);
            m_rect.setLeft(0);
            m_move = true;

            event->accept();
            this->update();
            return;
        }
    }

    m_move = false;
    this->update();
    event->ignore();
}

void VProjectTreeWidget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    {
        QByteArray itemData = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
        QTreeWidgetItem *item = (QTreeWidgetItem*)((void*)QVariant(itemData).toULongLong());
        QTreeWidgetItem *pItem = itemAt(event->pos());
        if(pItem == item || pItem == nullptr )
        {
            event->ignore();
            return;
        }

        auto item_data = get_item_data(item);
        if(is_item_contain(pItem, item->text(0), item_data.type))
        {
            QMessageBox::critical(this, "移动失败", "该目录下已经有同名文件", QMessageBox::Yes);
            event->ignore();
            return;
        }

        item->parent()->removeChild(item);

        int type = get_item_data(item).type;
        pItem->addChild(item);

        // 排序
        sort_item_child(pItem);

        // item setting
        pItem->setExpanded(true);
        this->setCurrentItem(item);

        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
    else
    {
        event->ignore();
    }

    QTreeWidget::dropEvent(event);

}

void VProjectTreeWidget::startDrag(Qt::DropActions supportedActions)
{
    QTreeWidgetItem *item = currentItem();
        if(item == NULL)
            return;

    if(is_custom_folder_child(item) == false){
        return;
    }

    QString pValue = QString::number(unsigned long long ((void*)item));
    QByteArray itemData;
    itemData = QVariant(pValue).toByteArray();

    QMimeData *mimeData = new QMimeData;
    mimeData->setData("application/x-qabstractitemmodeldatalist", itemData);

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);

    //设置鼠标移动时，拖动的图片数据
    //QPixmap pPixmap(":/Drag.png");
    //pPixmap = pPixmap.scaledToWidth(2);
    //drag->setPixmap(pPixmap);
    //drag->setHotSpot(QPoint(drag->pixmap().width()/2, drag->pixmap().height()/2));

    if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
    {
        update_esln(item);
    }

    m_move = false;
    this->update();
//    delete mimeData;
//    delete drag;
}

void VProjectTreeWidget::paintEvent(QPaintEvent *event)
{
    QTreeView::paintEvent(event);

    QPainter painter(this->viewport());


    if(m_move)
    {
        QPen pen(painter.pen());
        pen.setWidth(2);
        painter.setPen(pen);
        painter.drawRect(m_rect);
    }

}

bool VProjectTreeWidget::event(QEvent *e)
{
    if (e->type() == QEvent::ToolTip)
    {
        qDebug() << "toolTIp";
    }
    return QTreeWidget::event(e);
}

bool VProjectTreeWidget::is_parent(QTreeWidgetItem *parent_item, QTreeWidgetItem *item)
{
    QTreeWidgetItem *temp;
    temp = item;
    while(temp = temp->parent(), temp != nullptr)
    {
        if(temp == parent_item)
        {
            return true;
        }
    }
    return false;
}

QTreeWidgetItem *VProjectTreeWidget::get_top_item(QTreeWidgetItem *item)
{
    QTreeWidgetItem * temp;
    temp = item;
    while(temp->parent() != nullptr)
    {
        temp = temp->parent();
    }
    return temp;
}

bool VProjectTreeWidget::is_item_contain(QTreeWidgetItem *item, QString text, int type)
{
    for(int i=0; i<item->childCount(); i++)
    {
        auto data = get_item_data(item->child(i));
        if(item->child(i)->text(0) == text &&
                type == data.type)
        {
            return true;
        }
    }
    return false;
}

void VProjectTreeWidget::update_esln(QTreeWidgetItem *item)
{
    QString esln_path = get_project_esln_path(item);
    QJsonObject root = get_prject_custom_folder(item);

    QString text = VFunctions::read_file_text(esln_path);
    QJsonParseError json_error;
    QJsonDocument json_document = QJsonDocument::fromJson(text.toUtf8(), &json_error);
    if(json_error.error != QJsonParseError::NoError)
    {
        QMessageBox::critical(this, "错误", QString("%1 解析失败").arg(esln_path), "确定");
        return ;
    }

    QJsonObject object = json_document.object();
    object.insert("root", root);

    json_document.setObject(object);
    VFunctions::save_file(esln_path, json_document.toJson());
//    VFunctions::save_file("d:/1.json", json_document.toJson());

    // 重新载入 project
    emit signal_reload_project(esln_path);
}

QTreeWidgetItem *VProjectTreeWidget::get_project_folder(QTreeWidgetItem *project, int type)
{
    for(int i=0; i<project->childCount(); i++)
    {
        auto data = get_item_data(project->child(i));
        if(data.type == type)
        {
            return project->child(i);
        }
    }
    return nullptr;
}

QTreeWidgetItem *VProjectTreeWidget::get_project_item(QString path)
{
    auto root = this->invisibleRootItem();
    for (int i = 0; i < root->childCount(); i++)
    {
        if (get_project_esln_path(root->child(i)) == path)
        {
            return root->child(i);
        }
    }
    return nullptr;
}

bool VProjectTreeWidget::is_custom_folder_child(QTreeWidgetItem *item)
{
    auto temp = item;
    while(temp->parent() != nullptr){
        if(get_item_data(temp).type == TreeWidgetItemType::CUSTOM_FOLDER){
            return true;
        }
        temp = temp->parent();
    }
    return false;
}

void VProjectTreeWidget::recursion_project_contain(QTreeWidgetItem *item, QString text)
{
    for(int i=0; i<item->childCount(); i++)
    {
        auto child = item->child(i);
        if(child->text(0) == text)
        {
            m_comtain = true;
        }

        recursion_project_contain(child, text);
    }
}

QString VProjectTreeWidget::get_project_esln_path(QTreeWidgetItem *item)
{
    auto top_item = get_top_item(item);
    return get_item_data(top_item).path;
}

QString VProjectTreeWidget::get_item_path(QTreeWidgetItem *item)
{
    return get_item_data(item).path;
//    QString result;
//    QString project_folder_path = QFileInfo(get_project_esln_path(item)).path();
//    auto data = get_item_data(item);
//    QDir dir;
//    dir.setCurrent(project_folder_path);
//    result = data.path;
//    if(dir.isRelativePath(result))
//    {
//        dir.cd(result);
//        result = dir.absolutePath();
//    }
//    qDebug() << result + "/" + item->text(0);
//    return result + "/" + item->text(0);
}

QString VProjectTreeWidget::get_project_source_path(QTreeWidgetItem *item)
{
    QString path = get_project_esln_path(item);
    return QFileInfo(path).path();
}

void VProjectTreeWidget::sort_item_child(QTreeWidgetItem *item)
{
    QList<QTreeWidgetItem*> child_list;
    for(int i=0; i<item->childCount(); i++)
    {
        child_list.append(item->child(i));
    }

    foreach(QTreeWidgetItem *child, child_list)
    {
        item->removeChild(child);
    }

    QList<QTreeWidgetItem*> folder_list;
    QList<QTreeWidgetItem*> other_list;

    foreach(QTreeWidgetItem *child, child_list)
    {
        if(get_item_data(child).type == TreeWidgetItemType::FOLDER)
        {
            folder_list.append(child);
        }
        else
        {
            other_list.append(child);
        }
    }

    folder_list = sort_item_list(folder_list);
    other_list = sort_item_list(other_list);

    foreach(QTreeWidgetItem * member, folder_list + other_list)
    {
        item->addChild(member);
    }
}

QList<QTreeWidgetItem *> VProjectTreeWidget::sort_item_list(QList<QTreeWidgetItem *> list)
{
    QList<int> int_list;
    QList<QList<QTreeWidgetItem*>*> ptr_list;

    // 首字母添加
    foreach(QTreeWidgetItem * item, list)
    {
        int unicode = item->text(0).at(0).toUpper().unicode();

        if(int_list.contains(unicode) == false)
        {
            int_list.append(unicode);
            ptr_list.append(new QList<QTreeWidgetItem*>());
        }
    }

    // 首字母排序
    std::sort(int_list.begin(),int_list.end(),[](const int &a, const int &b)
    {
        return a < b;
    });

    // 项目整合
    foreach(QTreeWidgetItem * item, list)
    {
        int unicode = item->text(0).at(0).toUpper().unicode();
        ptr_list.at(get_member_of_list_index(unicode, int_list))->append(item);
    }

    // 项目排序
    foreach(QList<QTreeWidgetItem*>* ptr, ptr_list)
    {
        std::sort(ptr->begin(),ptr->end(),[](const QTreeWidgetItem *a, const QTreeWidgetItem *b)
        {
            return a->text(0) < b->text(0);
        });
    }

    // 整合返回
    QList<QTreeWidgetItem *> result;
    foreach(QList<QTreeWidgetItem*>* ptr, ptr_list)
    {
        foreach(QTreeWidgetItem* item, *ptr)
        {
            result.append(item);
        }
    }

    return result;
}

int VProjectTreeWidget::get_member_of_list_index(int member, QList<int> &list)
{
    for(int i=0; i<list.count(); i++)
    {
        if(list.at(i) == member)
        {
            return i;
        }
    }
    return -1;
}

bool VProjectTreeWidget::is_project_open(QString path)
{
    auto root = this->invisibleRootItem();
    for(int i=0; i<root->childCount(); i++)
    {
        auto item = root->child(i);
        if(get_item_data(item).path == path)
        {
            return true;
        }
    }
    return false;
}

void VProjectTreeWidget::recursion_project(QTreeWidgetItem *item, QJsonArray &root, QDir &dir)
{
    foreach(QJsonValue value, root)
    {
        QJsonObject child = value.toObject();
        QString name = child.value("name").toString();
        QTreeWidgetItem *folder_item = new QTreeWidgetItem(item);
        folder_item->setIcon(0, QIcon(VGlobal::icon_path.value("folder")));
        folder_item->setText(0, name);
        // folder_item->setA

        VProjectTreeWidget::VItemData data = VProjectTreeWidget::get_item_data(item);
        VProjectTreeWidget::set_item_data(folder_item, VProjectTreeWidget::TreeWidgetItemType::FOLDER,
                                          VProjectTreeWidget::get_project_source_path(item));
        // VProjectTreeWidget::set_item_data(item, folder_item, VProjectTreeWidget::TreeWidgetItemType::FOLDER);
//        VProjectTreeWidget::set_item_data(folder_item, data.id,
//                                          VProjectTreeWidget::TreeWidgetItemType::FOLDER,
//                                          data.esln_path, data.source_path, "");



        QJsonArray child_folder = child.value("folder").toArray();
        if(child_folder.count() > 0)
        {
            recursion_project(folder_item, child_folder, dir);
        }

        QJsonArray child_file = child.value("file").toArray();
        foreach(QJsonValue value, child_file)
        {
            QString path = dir.absoluteFilePath(value.toString());
            QString file_name = QFileInfo(path).fileName();

            QTreeWidgetItem *file_item = new QTreeWidgetItem(folder_item);
            file_item->setText(0, file_name);
            set_file_item_icon(file_item);
            VProjectTreeWidget::set_item_data(file_item, TreeWidgetItemType::FILE, path);
        }
    }

}

void VProjectTreeWidget::set_file_item_icon(QTreeWidgetItem *item)
{
    QString name = item->text(0);
    QString suffix = QFileInfo(name).suffix();

    if(suffix == "h")
    {
        item->setIcon(0, QIcon(VGlobal::icon_path.value("file_h")));
    }
    else if(suffix == "c")
    {
        item->setIcon(0, QIcon(VGlobal::icon_path.value("file_c")));
    }
    else if(suffix == "jpg" || suffix == "jpeg" || suffix == "png" || suffix == "bmp")
    {
        item->setIcon(0, QIcon(VGlobal::icon_path.value("file_img")));
    }
    else
    {
        item->setIcon(0, QIcon(VGlobal::icon_path.value("file_other")));
    }
}

void VProjectTreeWidget::contextMenuEvent(QContextMenuEvent *)
{
    switch (get_current_item_type())
    {
    case VProjectTreeWidget::TreeWidgetItemType::FILE:
        _content_menu.clear();
//        _content_menu.addAction(VGlobal::action.value("export_file"));
//        _content_menu.addAction(VGlobal::action.value("setting_file"));
        _content_menu.addAction(VGlobal::action.value("delete"));
        _content_menu.addAction(VGlobal::action.value("rename"));
//        _content_menu.addAction(VGlobal::action.value("access_file_homepage"));
        _content_menu.addAction(VGlobal::action.value("get_more"));
        _content_menu.exec(QCursor::pos());
        break;

    case VProjectTreeWidget::TreeWidgetItemType::PROJECT:
        _append_menu.clear();
        _append_menu.setTitle("添加");
        _append_menu.setIcon(QIcon(VGlobal::icon_path.value("append")));
        _append_menu.addAction(VGlobal::action.value("new_file"));
        _append_menu.addAction(VGlobal::action.value("add_file"));
        _append_menu.addAction(VGlobal::action.value("new_folder"));
        _append_menu.addAction(VGlobal::action.value("get_more"));

        _content_menu.clear();
        _content_menu.addMenu(&_append_menu);
        _content_menu.addAction(VGlobal::action.value("project_build"));
        _content_menu.addAction(VGlobal::action.value("set_project_active"));
        _content_menu.addAction(VGlobal::action.value("project_pack"));
        _content_menu.addAction(VGlobal::action.value("close_project"));
        _content_menu.addAction(VGlobal::action.value("access_project_homepage"));
        _content_menu.addAction(VGlobal::action.value("open_to_path"));
        _content_menu.addAction(VGlobal::action.value("project_attribute"));
        _content_menu.exec(QCursor::pos());
        break;

    case VProjectTreeWidget::TreeWidgetItemType::FOLDER:
        _content_menu.clear();
        _content_menu.addAction(VGlobal::action.value("new_file"));
        _content_menu.addAction(VGlobal::action.value("add_file"));
        _content_menu.addAction(VGlobal::action.value("new_folder"));
        _content_menu.addAction(VGlobal::action.value("delete"));
        _content_menu.addAction(VGlobal::action.value("rename"));
        _content_menu.addAction(VGlobal::action.value("get_more"));
        _content_menu.exec(QCursor::pos());
        break;
    }
}

void VProjectTreeWidget::on_doubleClicked()
{
    auto item = this->currentItem();
    if (item == nullptr) return;

    auto data = get_item_data(item);
    if (data.type == TreeWidgetItemType::FILE)
    {
        QFile file(data.path);
        if (file.exists())
        {
            emit signal_open_file(data.path);
        }
        else
        {
            // 文件不存在,弹出信息框提示用户.
            QMessageBox::critical(this, "文件打开失败", QString("路径 : %1 \r\n错误 : 文件不存在").arg(data.path), "确定");
        }
		if(item->childCount())
			item->setExpanded(!item->isExpanded());
    }else if(data.type == TreeWidgetItemType::ATTRIBUTE)
    {
        qDebug() << data.line;
        emit signal_jump(data.path, data.line);
    }
}

void VProjectTreeWidget::open_project(QString esln_path)
{
    // 判断当前工程是否已经打开了
    if(is_project_open(esln_path))
    {
        QMessageBox::information(this, "提示", QString("路径 : %1 \r\n信息 : 工程已经打开了").arg(esln_path), "确定");
        return;
    }

    QString project_json_text = VFunctions::read_file_text(esln_path);

    QJsonParseError json_error;
    QJsonDocument json_document = QJsonDocument::fromJson(project_json_text.toUtf8(), &json_error);
    if(json_error.error != QJsonParseError::NoError)
    {
        QMessageBox::critical(this, "错误", QString("%1 解析失败").arg(esln_path));
        return ;
    }

    QJsonObject root = json_document.object().value("root").toObject();
    auto project = new QTreeWidgetItem(this);
    project->setText(0, root.value("name").toString());
    project->setIcon(0, QIcon(VGlobal::icon_path.value("project")));
    project->setExpanded(true);
    set_item_data(project, TreeWidgetItemType::PROJECT, esln_path);
    //external_dependence


    auto external_dependence_item = new QTreeWidgetItem(project);
    external_dependence_item->setText(0, "外部依赖");
    external_dependence_item->setIcon(0, QIcon(VGlobal::icon_path.value("external_dependence")));
//    external_dependence_item->setExpanded(true);
    set_item_data(external_dependence_item, TreeWidgetItemType::FOLDER, esln_path);

    auto Modular_item = new QTreeWidgetItem(project);
    Modular_item->setText(0, "模块");
    Modular_item->setIcon(0, QIcon(VGlobal::icon_path.value("Modular")));
//    Modular_item->setExpanded(false);
    set_item_data(Modular_item, TreeWidgetItemType::FOLDER, esln_path);

    auto aaa =  new QTreeWidgetItem(Modular_item);
    aaa->setText(0, "尚未实现, 敬请期待");

    auto item = new QTreeWidgetItem(project);
    item->setText(0, "文件管理");
    item->setIcon(0, QIcon(VGlobal::icon_path.value("folder")));
    item->setExpanded(true);
    set_item_data(item, TreeWidgetItemType::CUSTOM_FOLDER, esln_path);

    // 载入文件夹
    QDir dir;
    dir.setCurrent(QFileInfo(esln_path).path());
    QJsonArray folder_arr = root.value("folder").toArray();
    recursion_project(item, folder_arr, dir);

    // 载入文件
    QJsonArray file_arr = root.value("file").toArray();
    foreach(QJsonValue value, file_arr)
    {
        auto child = new QTreeWidgetItem(item);
        child->setText(0, value.toString());
        set_file_item_icon(child);
        VProjectTreeWidget::set_item_data(child, VProjectTreeWidget::TreeWidgetItemType::FILE,
                                          VProjectTreeWidget::get_project_source_path(item) + "/" + value.toString());
    }


    // 设置为活动项目
    set_active_project(esln_path);

    // 添加历史记录
    apped_historical_record(esln_path);

    // 通知打工程
    emit signal_open_project(esln_path);
}

QString VProjectTreeWidget::get_current_item_path()
{
    QTreeWidgetItem *item = this->currentItem();

    auto data = get_item_data(item);
    QString path = data.path;
    return path;

}

QString VProjectTreeWidget::get_current_project_path()
{
    QTreeWidgetItem *item = this->currentItem();
    QString esln_path = VProjectTreeWidget::get_project_esln_path(item);
    return esln_path;
}

int VProjectTreeWidget::get_current_item_type()
{
    if(currentItem() == nullptr)
    {
        return -1;
    }

    auto item = currentItem();
    auto data = get_item_data(item);
    return data.type;
}

void VProjectTreeWidget::access_file_homepage()
{
    auto current_item = this->currentItem();
    auto item_data = get_item_data(current_item);

    if(item_data.type == TreeWidgetItemType::FILE)
    {
        emit signal_access_file_homepage(item_data.path);
    }
}

bool VProjectTreeWidget::set_active_project(QString esln_path)
{
    bool result = false;

    // 获取原本的字体
    QFont font = this->invisibleRootItem()->child(0)->font(0);
    font.setBold(false);

    // 依照路劲设置qms的项目为粗体，其他项目取消粗体
    auto root = this->invisibleRootItem();
    for (int i = 0; i < root->childCount(); i++)
    {
        root->child(i)->setFont(0, font);
        if (get_project_esln_path(root->child(i)) == esln_path)
        {
            _active_project = esln_path;
            QFont bold_font(font);
            bold_font.setBold(true);
            root->child(i)->setFont(0, bold_font);
            result = true;
        }
    }
    return result;
}

void VProjectTreeWidget::close_project()
{
//    auto item = this->currentItem();
//    QString esln_path = VProjectTreeWidget::get_project_esln_path(item);
//    QStringList path_list = VFunctions::get_project_all_file_path(esln_path);


//    // 检测 file_list 中的文件是否打开了
//    // 如果打开看是否修改
//    // 否则直接关闭
//    // 全部关闭后 关闭项目


//    foreach(QString path, path_list)
//    {
//        int result = close_file(path);
//        if(result == CloseStatus::CANCEL)
//        {
//            return;
//        }
//    }

//    // 移除项目
//    auto root = _project_treewidget->invisibleRootItem();
//    root->removeChild(item);

//    // 判断关闭的是不是活动项目
//    if(esln_path == _active_project_path)
//    {
//        _active_project_path = "";
//        if(root->childCount() > 0)
//        {
//            // 设置第一个为活动项目
//            QString path = get_project_esln_path(root->child(0));
//            set_active_project(path);
//        }
//    }
}

void VProjectTreeWidget::export_file()
{
    auto item =  this->currentItem();
    QString path = VProjectTreeWidget::get_item_data(item).path;
    QString name = QFileInfo(path).fileName();
    QString suffix = QFileInfo(path).suffix();

    QString save_path = QFileDialog::getSaveFileName(this, "导出文件", name, "文件 (*." + suffix + ")");
    if(save_path.isEmpty() == false)
    {
        // 判断是否存在同名文件
        if(QFile(save_path).exists())
        {
            QFile(save_path).remove();
        }

        QFile::copy(path, save_path);
    }
}

void VProjectTreeWidget::init()
{
    // connect
    QObject::connect(this, &VProjectTreeWidget::doubleClicked, this, &VProjectTreeWidget::on_doubleClicked);
//    QObject::connect(this, &VProjectTreeWidget::currentItemChanged, this, &VProjectTreeWidget::on_currentItemChanged);

    QObject::connect(VGlobal::action.value("new_file"), &QAction::triggered, this, &VProjectTreeWidget::on_new_file);
    QObject::connect(VGlobal::action.value("add_file"), &QAction::triggered, this, &VProjectTreeWidget::on_add_file);
    QObject::connect(VGlobal::action.value("export_file"), &QAction::triggered, this, &VProjectTreeWidget::on_export_file);
    QObject::connect(VGlobal::action.value("delete"), &QAction::triggered, this, &VProjectTreeWidget::on_delete);
    QObject::connect(VGlobal::action.value("rename"), &QAction::triggered, this, &VProjectTreeWidget::on_rename);
    QObject::connect(VGlobal::action.value("new_folder"), &QAction::triggered, this, &VProjectTreeWidget::on_new_folder);
    QObject::connect(VGlobal::action.value("set_project_active"), &QAction::triggered, this, &VProjectTreeWidget::on_set_project_active);
}

void VProjectTreeWidget::remove_project(QTreeWidgetItem *item)
{
    QString esln_path = get_project_esln_path(item);

    // 移除项目
    auto root = this->invisibleRootItem();
    root->removeChild(item);

    // 判断关闭的是不是活动项目
    if(esln_path == _active_project)
    {
        _active_project = "";
        if(root->childCount() > 0)
        {
            // 设置第一个为活动项目
            QString path = get_project_esln_path(root->child(0));
            set_active_project(path);
        }
    }
}

bool VProjectTreeWidget::apped_historical_record(QString path)
{
    // 统一符号
    path = path.replace("\\", "/");

    QString text = VFunctions::read_file_text(VGlobal::historical_record_path);
    text = text.replace(path+"\r\n", "");
    text = path + "\r\n" + text;
    VFunctions::save_file(VGlobal::historical_record_path, text);
	return true;
}

bool VProjectTreeWidget::is_project_contain_file(QTreeWidgetItem *item, QString text)
{
    m_comtain = false;

    auto top_item = get_top_item(item);
    for(int i=0; i<top_item->childCount(); i++)
    {
        recursion_project_contain(top_item->child(i), text);
    }

    return m_comtain;
}

VProjectTreeWidget::VItemData VProjectTreeWidget::get_item_data(QTreeWidgetItem *item)
{
    VItemData result;
    result = item->data(1, Qt::UserRole).value<VItemData>();
    return result;

}

void VProjectTreeWidget::set_item_data(QTreeWidgetItem *item, int type, QString path)
{
    VItemData data;
    data.type = type;
    data.path = path;
    item->setData(1, Qt::UserRole, QVariant::fromValue(data));
}

QJsonObject VProjectTreeWidget::get_prject_custom_folder(QTreeWidgetItem *item)
{
    auto top_item = get_top_item(item);
    auto data = get_item_data(top_item);
    auto custom_item = get_project_folder(top_item, TreeWidgetItemType::CUSTOM_FOLDER);
    if(custom_item == nullptr) return QJsonObject();

//    qDebug() << top_item->text(0);
    QDir dir;
    dir.setCurrent(QFileInfo(data.path).path());
    QJsonArray arr;
    recursion_item(custom_item, arr, dir);
    return arr.at(0).toObject();
}

void VProjectTreeWidget::recursion_item(QTreeWidgetItem *item, QJsonArray &arr, QDir &dir)
{
    QJsonObject object;
    QJsonArray file_arr;
    QJsonArray folder_arr;

    object.insert("name", item->text(0));

    for(int i=0; i<item->childCount(); i++)
    {
        auto temp = item->child(i);
        auto data = get_item_data(temp);

        if(data.type == TreeWidgetItemType::FILE)
        {
            file_arr.append(dir.relativeFilePath(data.path));
        }
        else if(data.type == TreeWidgetItemType::FOLDER)
        {
            recursion_item(temp, folder_arr, dir);
        }

    }

    object.insert("file", file_arr);
    object.insert("folder", folder_arr);

    arr.append(QJsonValue(object));
}

void VProjectTreeWidget::on_add_file()
{
    auto item = this->currentItem();
    if(item == nullptr) return;
    QString esln_path = get_project_esln_path(item);
    QString source_path = QFileInfo(esln_path).path();
    QStringList paths = QFileDialog::getOpenFileNames(this, "添加文件", source_path, "所有文件 (*.*);;头文件(*.h);;源文件(*.c)");
    if(paths.count() > 0)
    {
        QDir dir;
        dir.setCurrent(source_path);

        QStringList exists_file_list = VProjectData::get_names(esln_path);
        QStringList not_add_names;
        foreach(QString path, paths)
        {
            QFileInfo info(path);
            QString name = info.fileName();
            if(exists_file_list.contains(name)){
                not_add_names.append(name);
                continue;
            }

            QString relativeFilePath = dir.relativeFilePath(path);

            // 添加item
            auto file_item = new QTreeWidgetItem(item);
            file_item->setText(0, name);
            set_file_item_icon(file_item);
            set_item_data(file_item, TreeWidgetItemType::FILE, QFileInfo(relativeFilePath).path());
        }

        // 项目排序
        sort_item_child(item);

        // update esln
        update_esln(item);

        // item setting
        item->setExpanded(true);
//        this->setCurrentItem(file_item);

        // 提示没有添加进去的文件
        if(not_add_names.count() > 0)
            QMessageBox::critical(this, "添加失败", "以下文件已经存在\n" + not_add_names.join('\n'));
    }
}

void VProjectTreeWidget::on_export_file()
{

}

void VProjectTreeWidget::on_delete()
{
    if(this->isActiveWindow())
    {
        auto current_item = this->currentItem();
		if (current_item == nullptr) return;
		QString esln_path = get_project_esln_path(current_item);
		QString base_name = QFileInfo(esln_path).baseName();
        auto parent = current_item->parent();
        auto item_data = get_item_data(current_item);

        if(item_data.type == TreeWidgetItemType::FOLDER)
        {
            int result = QMessageBox::warning(this, "移除文件夹",
                                              QString("此操作将移除文件夹<%1>\r\n及其该文件夹下的所有内容").arg(current_item->text(0)),
                                              "移除", "取消");

			qDebug() << result;
            if(result == 0)
            {
                parent->removeChild(current_item);

                // 更新esln
                update_esln(parent);
            }
        }
        else if(item_data.type == VProjectTreeWidget::TreeWidgetItemType::FILE)
        {
            auto new_dialog = new VRemoveFileDialog(this);
            new_dialog->setWindowTitle(QString("删除:%1").arg(QFileInfo(item_data.path).fileName()));

			//QMessageBox::question("文件操作", QString("选择\"移除\"可将\"%1\"从\"%2\"中移除。\r\n 选择\"删除\"可永久删除\"%3\"")
			//	.arg(current_item->text(0)).arg(base_name).arg(current_item->text(0)), "移除(&R)","删除(&D)");



            auto result = new_dialog->exec();
            if (result == QDialog::Rejected)
            {
                return;
            }

            if (new_dialog->_delete_source_file)
            {
                QFile file(get_item_path(current_item));
                if (file.exists())
                {
                    qDebug() << "同时删除文件";
                    file.remove();

					// 通知删除
					emit signal_delete_file(item_data.path);
                }
            }

            parent->removeChild(current_item);

            // 更新esln
            update_esln(parent);
        }
    }
}

void VProjectTreeWidget::on_new_file()
{
    auto item = this->currentItem();

    VInputDialog dlg(this);
    dlg.setWindowTitle("请输入文件名");
    int reuslt = dlg.exec();

    if(reuslt == QDialog::Accepted)
    {
        QString esln_path = get_project_esln_path(item);
        QString source_path = get_project_source_path(item);
        QString path = source_path + "/" + dlg.m_text;
        if(QFile(path).exists())
        {
            QMessageBox::critical(this, "创建失败", QString("路径 : %1\r\n错误 : 该文件已经存在").arg(path),
                                  "确定");
            return;
        }

        auto file_item = new QTreeWidgetItem(item);
        file_item->setText(0, dlg.m_text);
        set_file_item_icon(file_item);
        VProjectTreeWidget::set_item_data(file_item, TreeWidgetItemType::FILE, path);

        // create_file
        VFunctions::creat_file(path);

        // 项目排序
        sort_item_child(item);

        // update esln
        update_esln(item);

        // item setting
        item->setExpanded(true);
        this->setCurrentItem(file_item);
        emit signal_reload_project(esln_path);

    }
}

void VProjectTreeWidget::on_rename()
{
//    qDebug() << this->hasFocus();

    auto item = this->currentItem();
    if(item == nullptr) return;
    QString esln_path = get_project_esln_path(item);

    auto item_data = get_item_data(item);
    auto source_path = get_project_source_path(item);

    if(item_data.type == TreeWidgetItemType::FOLDER)
    {
        VInputDialog dlg(this);

        dlg.setTitle("文件夹重命名");
        dlg.lineedit_set_text(item->text(0));
        dlg.lineedit_select_all();

        int result = dlg.exec();
        if(result == QDialog::Accepted)
        {
            if(item->text(0) == dlg.m_text)
            {
                return;
            }

            if(VProjectTreeWidget::is_item_contain(item->parent(), dlg.m_text, TreeWidgetItemType::FOLDER) == true)
            {
                QMessageBox::critical(this, "重命名失败", "该目录下已有同名文件夹", QMessageBox::Yes);
                return;
            }

            item->setText(0, dlg.m_text);

            // 项目排序
            sort_item_child(item->parent());

            // 更新esln
            update_esln(item);

            // 选中item
            this->setCurrentItem(item);
        }
    }
    else if(item_data.type == VProjectTreeWidget::TreeWidgetItemType::FILE)
    {
        VInputDialog dlg(this);
        dlg.setTitle("文件重命名");
        dlg.lineedit_set_text(item->text(0));
        dlg.lineedit_select_all();

        int result = dlg.exec();
        if(result == QDialog::Accepted)
        {
            if(item->text(0) == dlg.m_text)
            {
                return;
            }

            QString new_path = source_path + "/" + dlg.m_text;

            if(is_item_contain(item->parent(), dlg.m_text, TreeWidgetItemType::FILE) == true)
            {
                QMessageBox::critical(this, "重命名失败", "该目录下已有同名文件", "确定");
                return;
            }

            // 判断文件是否存在
            if(QFile(item_data.path).exists() == false)
            {
                QMessageBox::critical(this, "重命名失败", "文件不存在", "确定");
                return;
            }

            // 文件重命名
            QString path = get_item_path(item);
            QFile(path).rename(new_path);
            item->setText(0, dlg.m_text);
			set_item_data(item, TreeWidgetItemType::FILE, new_path);

            // 更新到后台
            emit signal_rename(path, new_path);

            // 项目排序
            sort_item_child(item->parent());

            // 更新esln
            update_esln(item);

            // 选中item
            this->setCurrentItem(item);
        }
    }
}

void VProjectTreeWidget::on_project_pack()
{
    QString path =  get_project_esln_path(this->currentItem());
    QString project_dir = QFileInfo(path).path();
    QString save_path = QFileDialog::getSaveFileName(this, "打包项目", "", "压缩文件 (*.zip)");

    if(save_path.isEmpty() == false)
    {
        // 如果存在则移除
        if(QFile(save_path).exists())
        {
            QFile(save_path).remove();
        }
        VFunctions::pack(project_dir, save_path);
    }

    //qDebug() << path;
}

void VProjectTreeWidget::slot_update_outline(QString path, QList<QTreeWidgetItem *> list)
{
    // 释放内存
    auto release = [](QList<QTreeWidgetItem *> &list){
        foreach(QTreeWidgetItem * item, list)
        {
            delete item;
        }
    };

    // 找出所有item
    QList<QTreeWidgetItem *> items;
    std::function<void(QTreeWidgetItem *item, QList<QTreeWidgetItem *> &result)> recursion;
    recursion = [&recursion, this](QTreeWidgetItem *item, QList<QTreeWidgetItem *> &result)
    {
        for(int i=0; i<item->childCount(); i++)
        {
            int type = get_item_data(item->child(i)).type;
            if(type == TreeWidgetItemType::FILE)
                result.append(item->child(i));
            else
                recursion(item->child(i), result);
        }
    };
    recursion(this->invisibleRootItem(), items);
    if(items.count() == 0){
        release(list);
        return;
    }

    foreach(QTreeWidgetItem*item, items)
    {
        if(get_item_data(item).path == path)
        {
			qDebug() << item->text(0);
            item->takeChildren();
            item->addChildren(list);
            return;
        }
    }
    release(list);
}

void VProjectTreeWidget::slot_update_project_external_dependence(QString esln_path, QList<QTreeWidgetItem *> list)
{
    auto find_project = [this](QString &path)->QTreeWidgetItem *{
            auto root = this->invisibleRootItem();
            for (int i = 0; i < root->childCount(); i++)
            {
                if (get_project_esln_path(root->child(i)) == path)
                {
                    return root->child(i);
                }
            }
            return nullptr;
    };

    // 释放内存
    auto release = [](QList<QTreeWidgetItem *> &list){
        foreach(QTreeWidgetItem * item, list)
        {
            delete item;
        }
    };


    auto project = find_project(esln_path);
    if(project == nullptr){
        release(list);
        return;}

	// 清空原来的
	project->child(0)->takeChildren();

	// 添加
    project->child(0)->addChildren(list);


}

void VProjectTreeWidget::on_set_project_active()
{
    if(this->currentItem() == nullptr) return;
    QString esln_path = get_project_esln_path(this->currentItem());
    set_active_project(esln_path);
}

void VProjectTreeWidget::on_project_attribute()
{
    // 读取配置
    auto item = this->currentItem();
    QString esln_path = get_project_esln_path(item);
    QJsonObject object = VFunctions::get_file_jsonDocument(esln_path).object();

    QString brand = object.value("brand").toString();
    QString mcu_type = object.value("mcu_type").toString();
    QString crystal = object.value("crystal").toString();
    QString homepage = object.value("homepage").toString();

    VProjectAttributeDialog *w;
    w = new VProjectAttributeDialog(this, esln_path);

//    w->set_brand(brand);
//    w->set_mcu_type(mcu_type);
//    w->set_crystal(crystal);
//    w->set_homepage_url(homepage);

    int result = w->exec();
    if(result == QDialog::Accepted)
    {
        emit signal_reload_project(esln_path);
    }
//    // 确定更改
//    if(result == QDialog::Accepted)
//    {
//        // 更新配置
////        object.insert("brand", w->m_brand);
////        object.insert("crystal", w->m_crystal);
////        object.insert("mcu_type", w->m_mcu_type);
////        object.insert("homepage", w->m_homepage_url);

//        QJsonDocument doc;
//        doc.setObject(object);
//        VFunctions::save_file(esln_path, doc.toJson());


//        // 发送信号 项目属性发生更改
//        emit signal_project_attribute_changed(esln_path);
//    }

}

void VProjectTreeWidget::on_new_folder()
{
    auto item = this->currentItem();

     VInputDialog dlg(this);
     dlg.setWindowTitle("输入文件夹名称");
     int result = dlg.exec();

     if(result == QDialog::Accepted)
     {
         if(is_item_contain(item, dlg.m_text, TreeWidgetItemType::FOLDER) == true)
         {
             QMessageBox::critical(this, "创建失败", "该目录下已有同名文件夹", QMessageBox::Yes);
             return;
         }

         QTreeWidgetItem *folder_item = new QTreeWidgetItem();
         folder_item->setIcon(0, QIcon(VGlobal::icon_path.value("folder")));
         folder_item->setText(0, dlg.m_text);
         VProjectTreeWidget::set_item_data(folder_item, VProjectTreeWidget::TreeWidgetItemType::FOLDER,
                                           VProjectTreeWidget::get_project_source_path(item));

         item->insertChild(0, folder_item);

         // 项目排序
         this->sort_item_child(item);

         // 更新esln
         this->update_esln(folder_item);

         // 选中item
         this->setCurrentItem(folder_item);
     }

}

